<template>
  <video :src="video" controls />
  <br />
  <button @click="transcode" :disabled="isProcessing">
    {{ isProcessing ? 'Processing...' : 'Start Transcode' }}
  </button>
  <button @click="downloadVideo" :disabled="!video" class="ml-2">
    Download Video
  </button>
  <button @click="showFileList" :disabled="!isFfmpegLoaded" class="ml-2">
    Show Files
  </button>
  <p>{{ message }}</p>
  <pre v-if="ffmpegLogs">{{ ffmpegLogs }}</pre>
  <pre v-if="fileList">{{ fileList }}</pre>
</template>

<script lang="ts">
import { FFmpeg } from '@ffmpeg/ffmpeg'
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
import { defineComponent, ref } from 'vue'

const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.9/dist/esm'
const videoURL = 'https://oss.baiweicaijing.com/v3/uploads/video/2025/07/22/61491584d89669f2c53b39106ccc15478aff4d.mp4'

export default defineComponent({
  name: 'App',
  setup() {
    const ffmpeg = new FFmpeg()
    const message = ref('Click Start to Transcode')
    const video = ref('')
    const isProcessing = ref(false)
    const isFfmpegLoaded = ref(false)
    const ffmpegLogs = ref('')
    const fileList = ref('')
    let downloadBlob: Blob | null = null

    async function transcode() {
      isProcessing.value = true
      message.value = 'Loading ffmpeg-core.js'
      ffmpegLogs.value = ''
      fileList.value = ''

      ffmpeg.on('log', ({ message: msg, type }: LogEvent) => {
        ffmpegLogs.value += `[${type}] ${msg}\n`
        if (type === 'error') {
          console.error('FFmpeg error:', msg)
        }
      })

      try {
        // 加载FFmpeg核心
        if (!isFfmpegLoaded.value) {
          await ffmpeg.load({
            coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
            wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
            workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
          })
          isFfmpegLoaded.value = true
        }

        // 检查输入文件是否可访问
        message.value = 'Checking input file'
        const response = await fetch(videoURL)
        if (!response.ok) {
          throw new Error(`Failed to fetch video: ${response.status} ${response.statusText}`)
        }

        // 获取并写入输入视频
        message.value = 'Fetching video data'
        const videoData = await fetchFile(videoURL)
        await ffmpeg.writeFile('input.mp4', videoData)

        // 验证输入文件大小
        const inputFile = await ffmpeg.readFile('input.mp4')
        if (inputFile.byteLength < 1024) {
          throw new Error(`Input file is too small (${inputFile.byteLength} bytes). Download failed.`)
        }

        // 尝试不同的FFmpeg命令组合
        message.value = 'Start transcoding'
        await ffmpeg.exec([
          '-i', 'input.mp4',
          '-c:v', 'libx264',
          '-crf', '23',
          '-preset', 'medium',
          '-c:a', 'aac',
          '-b:a', '128k',
          '-movflags', '+faststart', // 优化HTML5播放
          'output.mp4'
        ])

        // 验证输出文件
        const outputData = await ffmpeg.readFile('output.mp4')
        if (outputData.byteLength < 1024) {
          // 尝试使用更简单的命令
          message.value = 'Transcode attempt failed, trying alternative method'
          await ffmpeg.exec([
            '-i', 'input.mp4',
            '-c:v', 'copy', // 直接复制视频流，不重新编码
            '-c:a', 'copy', // 直接复制音频流，不重新编码
            'output_simple.mp4'
          ])

          const simpleOutput = await ffmpeg.readFile('output_simple.mp4')
          if (simpleOutput.byteLength < 1024) {
            // 尝试检测输入文件信息
            await ffmpeg.exec([
              '-i', 'input.mp4',
              '-f', 'null',
              '-'
            ])
            throw new Error(`Both transcode methods failed. Input file info logged above.`)
          }

          downloadBlob = new Blob([(simpleOutput as Uint8Array).buffer], { type: 'video/mp4' })
          video.value = URL.createObjectURL(downloadBlob)
          message.value = 'Transcoding completed using direct copy! Click Download to save.'
        } else {
          downloadBlob = new Blob([(outputData as Uint8Array).buffer], { type: 'video/mp4' })
          video.value = URL.createObjectURL(downloadBlob)
          message.value = 'Transcoding completed! Click Download to save.'
        }
      } catch (error) {
        console.error('Transcode error:', error)
        message.value = 'Error: ' + (error as Error).message
      } finally {
        isProcessing.value = false
      }
    }

    function downloadVideo() {
      if (!downloadBlob) return

      const link = document.createElement('a')
      link.href = video.value
      link.download = 'converted-video.mp4'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    }

    async function showFileList() {
      if (!isFfmpegLoaded.value) return

      try {
        const files = await ffmpeg.execute(['-hide_banner', '-filters'])
        fileList.value = files.toString()
      } catch (error) {
        fileList.value = 'Error fetching file list: ' + (error as Error).message
      }
    }

    return {
      video,
      message,
      transcode,
      downloadVideo,
      isProcessing,
      ffmpegLogs,
      fileList,
      showFileList,
      isFfmpegLoaded
    }
  }
})
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

button {
  padding: 8px 16px;
  margin: 4px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

pre {
  text-align: left;
  margin: 10px auto;
  padding: 10px;
  background-color: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 4px;
  max-width: 800px;
  max-height: 300px;
  overflow: auto;
}
</style>